package com.chuangjiangx.member.manager.client.web.coupon.compensator;

import com.chuangjiangx.domain.shared.model.Compensator;
import com.chuangjiangx.member.coupon.ddd.domain.model.VerifyWxCodeCompensator;
import com.chuangjiangx.member.coupon.ddd.domain.service.CouponDomainService;
import com.chuangjiangx.member.manager.client.web.coupon.compensator.Handle.WxVerifyHandle;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.concurrent.*;

import static com.chuangjiangx.commons.constant.CompensatorBusinessConstant.WX_VERIFY_ERROR;
import static com.chuangjiangx.commons.constant.CompensatorConstant.MEMBER_MANAGER_API_KEY;

/**
 * Created by Lenovo on 2018/9/4.
 * 错误补偿bean
 * 有全局错误补偿操作新建一个守护线程（deamon），在bean里启动，守护线程也需要在spring容器中注册
 * afterPropertiesSet会在bean加载完成之后执行
 */
@Component
public class CompensatorBean implements InitializingBean {
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private ObjectMapper mapperObject;
    @Autowired
    private CouponDomainService couponDomainService;
    @Override
    public void afterPropertiesSet() throws Exception {
        //线程池 池内线程为守护线程 放置查询线程
        ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(1,
                (Runnable r)->{
                    Thread t = Executors.defaultThreadFactory().newThread(r);
                    t.setDaemon(true);
                    return t;
                });
        //处理线程线程池 10个
        ExecutorService handleExecutorService =new ThreadPoolExecutor(10, 10,
                0L, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<>(2000));
        //启动守护线程
        executorService.scheduleAtFixedRate(()->{
            //固定 左进 右出 队列
//            System.out.println("running!!running!!running!!running!!running!!");
            String rpop = redisTemplate.execute((RedisConnection redisConnection)-> {
                List<byte[]> bytes = redisConnection.bRPop(0,MEMBER_MANAGER_API_KEY.getBytes());
                if(CollectionUtils.isEmpty(bytes)){
                    return null;
                }
                return (String)redisTemplate.getValueSerializer().deserialize(bytes.get(1));
            });
            if(rpop!=null){
                try{
                    Compensator compensator = mapperObject.readValue(rpop, Compensator.class);
                    if(compensator==null){
                        return;
                    }
                    if(WX_VERIFY_ERROR.equals(compensator.getBusiness())){
                        VerifyWxCodeCompensator verifyWxCodeCompensator =  mapperObject.readValue(rpop, VerifyWxCodeCompensator.class);
                        handleExecutorService.execute(new WxVerifyHandle(couponDomainService,verifyWxCodeCompensator,redisTemplate));
                    }else{
                        //没有获取到解决方法 存回去
                        redisTemplate.opsForList().leftPush(MEMBER_MANAGER_API_KEY,rpop);
                    }
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        },10,5, TimeUnit.MINUTES);
    }
}
